<template>
  <el-dialog v-model="modelVisible" width="800" align-center center @close="handleClose">
    <template #header>
      <CustomTitle title="批量导入商品" />
    </template>
    <el-tabs v-model="active" class="tabs-container" @tab-change="change">
      <el-tab-pane label="导入文件表" :name="1"></el-tab-pane>
      <el-tab-pane label="下载模板文件" :name="2"></el-tab-pane>
      <el-tab-pane label="上传记录" :name="3"></el-tab-pane>
    </el-tabs>
    <div class="hint" v-if="active != 2 && isShowInducts">
      <div>
        <el-icon> <WarningFilled /> </el-icon>如果数据处理出现任何错误，根据系统提示进行修改您的库存文件，然后重新上传。
      </div>
      <span @click="isShowInducts = false">不再提示</span>
    </div>
    <div class="hint" v-if="active == 2 && isShowDownTemp">
      <div>
        <el-icon> <WarningFilled /> </el-icon>选择需要导入的商品分类模板，完善对应模板的关联数据后下载，根据模板内容填写商品信。
      </div>
      <span @click="isShowDownTemp = false">不再提示</span>
    </div>
    <div v-if="active == 1">
      <el-upload v-if="!uploading" class="upload-demo" drag :http-request="customRequest" multiple :show-file-list="false">
        <img src="@/assets/images/upload.png" alt="" />
        <div class="el-upload__text">
          <em>上传文件</em>
          <div class="tip">也可以拖拽到此处上传（支持格式：xlsx）</div>
        </div>
        <template #tip>
          <div class="el-upload__tip" @click="active = 2">
            <el-icon>
              <Paperclip />
            </el-icon>
            去下载模板
          </div>
        </template>
      </el-upload>
      <div v-else class="uploading" :style="{ '--color': status == 'success' ? '#2BA471' : '#D54941' }">
        <el-progress v-if="status == 'loading'" type="circle" :percentage="percentage" />
        <div v-else-if="status == 'success'">
          <el-icon>
            <CircleCheck />
          </el-icon>
        </div>
        <div v-else-if="status == 'error'">
          <el-icon>
            <CircleClose />
          </el-icon>
        </div>
        <div class="status">{{ statusList[status].title }}</div>
        <div class="tip">{{ statusList[status].tip }}</div>
        <div class="dialog-footer">
          <el-button @click="handleOpen" v-if="status == 'success'">留在当前页面</el-button>
          <el-button type="primary" @click="next">
            {{ statusList[status].btnText }}
          </el-button>
        </div>
        <div class="success-tip" v-if="status == 'success'">
          <div>完善内容与检查事项：</div>
          <div>
            1、上传商品主图，商品视频<br />
            2、上传商品详情页<br />
            3、检查商品标题，型号，质保模板，商品属性，确认<br />
            4、商品SKU，与商品价格，检查<br />
            5、完善并检查没问题后可提交上架<br />
          </div>
        </div>
        <div class="success-tip" v-if="status == 'error'" v-html="errorMsg"></div>
      </div>
    </div>
    <div v-else-if="active == 2">
      <div class="pla-title">选择需要导入的商品类目</div>
      <div class="content">
        <!-- <div class="search-box">
          <el-input v-model="classSearch" placeholder="请输入商品关键词搜索类目，如：“沙发”" />
          <div class="search" @click="getClassifyList">
            <el-icon>
              <Search />
            </el-icon>
          </div>
        </div> -->
        <div class="select">
          <span></span>
          <el-cascader
            :options="classify"
            v-model="categoryId"
            style="flex: 1"
            :props="{ label: 'name', value: 'categoryId' }"
            :show-all-levels="true"
            clearable
            filterable
          />
        </div>
        <div class="often">
          <div class="often-title">您经常使用的类目</div>
          <el-scrollbar max-height="120px">
            <div class="often-list" v-if="oftenList.length">
              <div v-for="item in oftenList" :key="item.categoryId" @click="useClassify(item.categoryId)">
                {{ item.categoryName }}
              </div>
            </div>
          </el-scrollbar>
        </div>
      </div>
    </div>
    <div v-if="active == 3" class="table">
      <div class="row">
        <div>上传日期</div>
        <div>文件名称</div>
        <div>上传状态</div>
        <div>操作</div>
      </div>
      <el-scrollbar max-height="300px" ref="scrollRef" @scroll="scroll">
        <el-empty :image-size="100" v-if="!recordList.length" />
        <div class="row" v-for="item in recordList" :key="item.createId">
          <div>{{ item.createTime }}</div>
          <div>{{ item.fileName }}</div>
          <div>{{ item.leadStatus == 1 ? "完成" : "失败" }}</div>
          <div class="operate">
            <img src="@/assets/images/download.png" alt="" @click="downFile(item.fileUrl, item.fileName)" />
            <img src="@/assets/images/del.png" alt="" @click="openDel(item.id)" />
          </div>
        </div>
      </el-scrollbar>
    </div>
    <template #footer v-if="active == 2">
      <div class="dialog-footer">
        <el-button @click="modelVisible = false">取消</el-button>
        <el-button type="primary" @click="downTemp" v-if="categoryId"> 下载此类模板 </el-button>
      </div>
    </template>
  </el-dialog>
  <!-- 操作提示 -->
  <el-dialog v-model="sureVisibel" width="400" align-center center :show-close="false">
    <div class="sure">
      <div>
        <el-icon>
          <Warning />
        </el-icon>
      </div>
      <span>删除记录后，将无法再次找回此文件，你还要继续吗？</span>
    </div>
    <template #footer>
      <div class="dialog-footer">
        <el-button @click="sureVisibel = false">取消</el-button>
        <el-button type="primary" @click="delRecord"> 确定 </el-button>
      </div>
    </template>
  </el-dialog>
</template>

<script setup>
import { ref, computed, onMounted } from "vue";
import { ElMessage } from "element-plus";
import CustomTitle from "@/components/CustomTitle/index.vue";
import { useLocalStorage } from "@vueuse/core";
import upload from "@/utils/upload";
import {
  importTemplate,
  getUserCategoryList,
  downTempFile,
  saveOftenCategory,
  getUploadRecord,
  getCategoryTree,
  deleteUploadRecord
} from "@/apis/manage";
import { Search } from "@element-plus/icons-vue";

const scrollRef = ref(null);
const active = ref(1);
const categoryId = ref();
const isShowInducts = useLocalStorage("isShowInducts", true);
const isShowDownTemp = useLocalStorage("isShowDownTemp", true);
const props = defineProps({
  visible: {
    type: Boolean,
    default: false
  }
});
const emit = defineEmits(["update:visible", "ok"]);

const record = ref({
  page: 1,
  size: 10
});
const sureVisibel = ref(false);
const classify = ref([]);
const modelVisible = computed({
  get: () => {
    return props.visible;
  },
  set: val => {
    emit("update:visible", val);
  }
});
const percentage = ref(0);
const uploading = ref(false);
const oftenList = ref([]);
const recordList = ref([]);
const closeUpload = ref(false);
const recordTotal = ref(0);
const classSearch = ref("");
const errorMsg = ref("");
const customRequest = async options => {
  uploading.value = true;
  closeUpload.value = false;
  const file = await upload(options, undefined, async percent => {
    const num = (percent * 100).toFixed(2);
    percentage.value = num;
  });
  if (!closeUpload.value) {
    const formData = new FormData();
    formData.append("file", options.file);
    try {
      await importTemplate(file.url, formData);
      status.value = "success";
    } catch (error) {
      errorMsg.value = error.message.replace(/,/g, "; ");
      status.value = "error";
    }
  }
};
const status = ref("loading");
const statusList = {
  loading: { title: "正在导入...", tip: "正在请求权限，大约剩余5s", btnText: "取消上传" },
  success: {
    title: "导入商品成功",
    tip: "导入商品成功，商品导入后存放在预发布商品列表，需要进行补充商品部份信息后，提交商品上架。",
    btnText: "前往预发布"
  },
  error: {
    title: "出错了",
    tip: "失败原因。您导入的数据模板中，存在必填项数据缺失，根据提示内容，请补充完整后重新导入",
    btnText: "我知道了"
  }
};
const useClassify = id => {
  let arr = [];
  const traverse = tree => {
    for (const v of tree) {
      if (v.categoryId == id) {
        arr.unshift(v.categoryId);
        return v.categoryId;
      } else if (v.children && v.children.length) {
        if (traverse(v.children)) {
          arr.unshift(v.categoryId);
          return v.categoryId;
        }
      }
    }
    return null;
  };
  traverse(classify.value);
  categoryId.value = arr;
};
const getRecord = async () => {
  const res = await getUploadRecord(record.value);
  recordList.value = [...recordList.value, ...res.data.records];
  recordTotal.value = res.data.total;
};
const scroll = ({ scrollTop }) => {
  const { scrollHeight, clientHeight } = scrollRef.value.wrapRef;
  if (scrollTop + clientHeight >= scrollHeight) {
    if (recordTotal.value > record.value.size && Math.ceil(recordTotal.value / record.value.size) > record.value.page) {
      record.value.page += 1;
      getRecord();
    }
  }
};
const next = () => {
  switch (status.value) {
    case "loading":
      closeUpload.value = true;
      uploading.value = false;
      status.value = "loading";
      break;
    case "error":
      uploading.value = false;
      status.value = "loading";
      break;
    case "success":
      emit("ok");
      modelVisible.value = false;
      break;
    default:
      break;
  }
};
const handleClose = () => {
  if (status.value === "success") {
    emit("ok");
  }
};
// 留在当前页
const handleOpen = () => {
  modelVisible.value = false;
  emit("ok");
};
const getName = (tree, id) => {
  for (const v of tree) {
    if (v.children && v.children.length) {
      if (getName(v.children, id)) return getName(v.children, id);
    } else {
      if (v.categoryId == id) {
        return v.name;
      }
    }
  }
  return null;
};
const delId = ref("");
const openDel = id => {
  delId.value = id;
  sureVisibel.value = true;
};
const delRecord = async () => {
  sureVisibel.value = false;
  await deleteUploadRecord(delId.value);
  ElMessage.success("删除成功");
  record.value.page = 1;
  recordList.value = [];
  getRecord();
};
const downFile = (url, name) => {
  const a = document.createElement("a");
  a.href = url;
  a.download = name;
  a.click();
};
const downTemp = async () => {
  const id = categoryId.value[categoryId.value.length - 1];
  const res = await downTempFile(id);
  let url = window.URL.createObjectURL(res);
  downFile(url, id + "-" + getName(classify.value, id) + ".xlsx");
  await saveOftenCategory(id);
  setTimeout(() => {
    URL.revokeObjectURL(url);
  }, 100);
};
const getOftenList = async () => {
  const res = await getUserCategoryList();
  oftenList.value = res.data;
};
const change = key => {
  switch (key) {
    case 1:
      break;
    case 2:
      getClassifyList();
      getOftenList();
      break;
    case 3:
      getRecord();
      break;
    default:
      break;
  }
};
const getClassifyList = async () => {
  const res = await getCategoryTree(classSearch.value);
  classify.value = res.data;
};
onMounted(() => {
  getClassifyList();
});
</script>

<style lang="scss" scoped>
$topic: #007dff;

.tabs-container {
  ::v-deep(.el-tabs__nav-wrap::after) {
    height: 1px;
  }

  ::v-deep(.el-tabs__item.is-active) {
    color: $topic;
  }

  ::v-deep(.el-tabs__active-bar) {
    background: $topic;
  }

  ::v-deep(.el-tabs__item:hover) {
    color: $topic;
  }
}

.hint {
  height: 54px;
  background: #e3f0fe;
  border-radius: 6px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 10px;

  div {
    display: flex;
    align-items: center;
    gap: 10px;

    ::v-deep(.el-icon) {
      color: #0052d9;
    }
  }

  span {
    font-size: 14px;
    color: rgba(0, 0, 0, 0.6);
    cursor: pointer;
  }
}

.upload-demo {
  margin-top: 20px;

  img {
    height: 80px;
    width: 80px;
  }

  em {
    color: $topic;
  }

  .tip {
    color: #86909c;
    font-size: 12px;
    margin-top: 10px;
  }

  .el-upload__tip {
    width: 150px;
    color: $topic;
    font-size: 16px;
    display: flex;
    align-content: center;
    gap: 8px;
    margin-top: 10px;
    user-select: none;

    .el-icon {
      font-size: 18px;
    }
  }
}

.uploading {
  background: #ffffff;
  border-radius: 10px;
  border: 1px dashed #c0c4cc;
  margin-top: 20px;
  padding-top: 40px;
  padding-bottom: 20px;
  box-sizing: border-box;

  > div {
    display: flex;
    justify-content: center;
  }

  .el-icon {
    font-size: 126px;
    color: var(--color);
  }

  .status {
    margin-top: 10px;
  }

  .tip {
    color: #86909c;
    font-size: 12px;
    margin-top: 10px;
    margin: 10px auto;
  }

  .success-tip {
    display: block;
    background: #f5f7fa;
    border-radius: 4px;
    margin-top: 20px;
    color: #4e5969;
    margin: 10px 10px 0;
    padding: 10px;
    font-size: 12px;
    line-height: 26px;
    white-space: pre-wrap;
    /* 或者 pre-line */
    word-wrap: break-word;
  }
}

.pla-title {
  color: #131414;
  font-size: 16px;
  margin: 20px 0;
}

.content {
  width: 80%;
  margin: 0 auto;

  .search-box {
    display: flex;

    ::v-deep(.el-input__wrapper) {
      border-radius: 4px 0 0 4px;
    }

    .search {
      background: $topic;
      border: 1px solid $topic;
      width: 50px;
      height: 30px;
      border-radius: 0 4px 4px 0;
      text-align: center;
      line-height: 30px;
      padding-top: 2px;

      .el-icon {
        color: white;
      }
    }
  }

  .often {
    border-radius: 4px;
    border: 1px solid #dcdfe6;
    margin: 6px 0 20px;
    padding-bottom: 10px;

    .often-title {
      color: #86909c;
      font-size: 12px;
      padding: 10px 10px 0 10px;
    }

    .often-list {
      display: flex;
      gap: 20px;
      flex-wrap: wrap;
      padding: 10px;

      > div {
        padding: 0 20px;
        background: #f7f9fa;
        height: 22px;
        line-height: 22px;
        border-radius: 4px;
        user-select: none;
      }
    }
  }

  .select {
    display: flex;
    width: calc(100% + 70px);
    margin-left: -70px;
    align-items: center;
    gap: 10px;

    span {
      width: 60px;
    }
  }
}

.dialog-footer {
  .el-button--primary {
    background: $topic;
    border-radius: 0;
    border: none;
  }

  .el-button {
    border-radius: 0;
  }
}

.table {
  $border: 1px solid #dcdfe6;
  margin-top: 20px;

  .row {
    display: grid;
    grid-template-columns: 1fr 2fr repeat(2, 1fr);
    border-bottom: $border;

    > div {
      height: 40px;
      display: flex;
      justify-content: center;
      align-items: center;
    }

    img {
      width: 20px;
      height: 20px;
    }

    .operate {
      display: flex;
      gap: 20px;
    }
  }

  > .row:first-child {
    background: #f2f6fc;
    border: none;
  }

  .row:last-child {
    border-bottom: none;
  }
}

.sure {
  text-align: center;

  ::v-deep(.el-icon) {
    font-size: 60px;
    margin-bottom: 20px;
    color: rgb(255, 51, 51);
  }
}
</style>
